package com.code;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES30;
import android.opengl.GLUtils;
import android.util.Log;

import com.graphics.GLRender;
import com.graphics.element.SkyCube;
import com.system.Camera;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import johnkkk.com.gl3x.R;


/**
 * @Author: clm
 * @Date: 2018-10-12
 */

public class SimpleGLRender extends GLRender {
    int vbo[] = new int[1];
    public Camera mCamera;
    private Context mContext;
    private SkyCube mSkyCube;
    public SimpleGLRender(Context context){
        mContext = context;
    }
    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
        super.onSurfaceCreated(gl10, eglConfig);
        mCamera = new Camera();
        mIGLLooper.init();
        //MatrixUtil.normalize(mCamera.mV_matrix);
        initScene();
    }
    private String vsSource = "\n" +
            "attribute vec3 pos;\n" +
            "attribute vec3 normal;\n" +
            "attribute vec2 uv;\n" +
            "varying vec3 Normal;\n" +
            "varying vec2 u_v;" +
            "uniform mat4 v_matrix;\n" +
            "uniform mat4 p_matrix;\n" +
            "void main()\n" +
            "{\n" +
            "gl_Position = p_matrix * v_matrix * vec4(pos, 1.0f);\n" +
            "Normal = normal;\n" +
            "u_v = uv;\n" +
            "}\n";
    private String fsSource = "\n" +
            "precision mediump float;\n" +
            "varying vec3 Normal;\n" +
            "varying vec2 u_v;\n" +
            "uniform sampler2D img;\n" +
            "uniform mat4 g;" +
            "void main()\n" +
            "{\n" +
            "gl_FragColor = texture2D(img, u_v);\n" +
//            "gl_FragColor = vec4(u_v.x, u_v.y, 0, 1);\n" +
            "}\n";
    private int mShaderProgram;
    //
    private float[] mVer = {
            //顶点属性
            -5.0f, -5.0f, -5.0f,
            5.0f, -5.0f, -5.0f,
            0.0f, 5.0f, -5.0f,
            //法线属性
            0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 1.0f,
    };
    private float vertices2[] = { // Positions // Normals // Texture Coords
            -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
            0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,
            0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
            0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
            -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,
            -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
            -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
            0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
            0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
            0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
            -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
            -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
            -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
            -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
            -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
            -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
            -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
            -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
            0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
            0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
            0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
            0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
            0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
            0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
            -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
            0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f,
            0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
            0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
            -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f,
            -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
            -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
            0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
            0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
            0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
            -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
            -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f };
    private FloatBuffer mFB;
    private FloatBuffer mLightFB;
    private int v_matrix_loc;
    private int p_matrix_loc;
    private int textID[] = new int[1];

    @Override
    public void onSurfaceChanged(GL10 gl10, int w, int h) {
        super.onSurfaceChanged(gl10, w, h);
        GLES30.glUseProgram(mShaderProgram);
        GLES30.glUniformMatrix4fv(p_matrix_loc, 1, false, mP_matrix, 0);
        GLES30.glUseProgram(0);
        mCamera.mP_matrix = mP_matrix;
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;//Opengl需要非压缩形式的原始数据
        List<Bitmap> bitmaps = new ArrayList<>();
        bitmaps.add(BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.right, options));
        bitmaps.add(BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.left, options));
        bitmaps.add(BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.top, options));
        bitmaps.add(BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.bottom, options));
        bitmaps.add(BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.front, options));
        bitmaps.add(BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.back, options));
        mSkyCube = new SkyCube("", mCamera, bitmaps);
    }

    /**
     * 初始化灯
     */
    public final void initLight(){

    }

    public final void initScene(){
        initLight();
        //创建vs和fs
        int vs = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER);
        int fs = GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER);
        GLES30.glShaderSource(vs, vsSource);
        GLES30.glCompileShader(vs);
        GLES30.glShaderSource(fs, fsSource);
        GLES30.glCompileShader(fs);

        //创建着色器程序
        mShaderProgram = GLES30.glCreateProgram();
        GLES30.glAttachShader(mShaderProgram, vs);
        GLES30.glAttachShader(mShaderProgram, fs);
        GLES30.glLinkProgram(mShaderProgram);


        //创建一个三角形
        ByteBuffer bb = ByteBuffer.allocateDirect(vertices2.length * 4);
        bb.order(ByteOrder.nativeOrder());
        mFB = bb.asFloatBuffer().put(vertices2);
        mFB.position(0);
        GLES30.glGenBuffers(1, vbo, 0);
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0]);
        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, 4 * mFB.limit(), mFB, GLES30.GL_STATIC_DRAW);

        //配置顶点属性
        GLES30.glUseProgram(mShaderProgram);
        int pos_loc = GLES30.glGetAttribLocation(mShaderProgram, "pos");
        GLES30.glVertexAttribPointer(pos_loc, 3, GLES30.GL_FLOAT, false, 4 * 8, 0);
        GLES30.glEnableVertexAttribArray(pos_loc);
        int normal_loc = GLES30.glGetAttribLocation(mShaderProgram, "normal");
        GLES30.glVertexAttribPointer(normal_loc, 3, GLES30.GL_FLOAT, false, 4 * 8, 4 * 3);
        GLES30.glEnableVertexAttribArray(normal_loc);
        int uv_loc = GLES30.glGetAttribLocation(mShaderProgram, "uv");
        GLES30.glVertexAttribPointer(uv_loc, 2, GLES30.GL_FLOAT, false, 4 * 8, 4 * 6);
        GLES30.glEnableVertexAttribArray(uv_loc);
        v_matrix_loc = GLES30.glGetUniformLocation(mShaderProgram, "v_matrix");
        p_matrix_loc = GLES30.glGetUniformLocation(mShaderProgram, "p_matrix");
        GLES30.glUseProgram(0);



        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);


        //纹理
        GLES30.glGenTextures(1, textID, 0);
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textID[0]);
        int width = 0, height = 0;
        ByteBuffer img = null;
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;//Opengl需要非压缩形式的原始数据
        final Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.wc_two_code, options);
        if(bitmap == null){
            GLES30.glDeleteTextures(1, textID, 0);
            Log.e("myLog", "纹理加载失败");
        }
        GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
        GLES30.glGenerateMipmap(GLES30.GL_TEXTURE_2D);
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);
        GLES30.glUseProgram(mShaderProgram);
        GLES30.glUniform1i(GLES30.glGetAttribLocation(mShaderProgram, "img"), 0);
        GLES30.glUseProgram(0);

        GLES30.glEnable(GLES30.GL_DEPTH_TEST);
        Log.e("myLog", "创建完成");
    }

    @Override
    public void onDrawFrame(GL10 gl10) {
        super.onDrawFrame(gl10);
        //gles2.x不支持vao,只能用vbo
        //gles3.x要求一定要使用vao
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);

        //updateCamera
        mCamera.updateCamera();

        GLES30.glUseProgram(mShaderProgram);
        GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textID[0]);
        GLES30.glUniformMatrix4fv(v_matrix_loc, 1, false, mCamera.mV_matrix, 0);
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0]);
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 36);
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
        GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);
        GLES30.glUseProgram(0);

        mSkyCube.render(0);
        GLES30.glFinish();
    }
}
